wayland: Pass shadow width to the compositor
authorCarlos Garnacho <carlosg@gnome.org>
Tue, 11 Nov 2014 11:07:24 +0000 (12:07 +0100)
committerCarlos Garnacho <carlosg@gnome.org>
Sun, 23 Nov 2014 12:11:08 +0000 (13:11 +0100)
Use xdg_surface_set_window_geometry() to tell the compositor about the
shadow widths, this makes some gnome-shell/mutter features (edge resistance,
frames around windows in the overview, side maximization, ...) work alright
with GTK+.

In order to add this, some other places in gdkwindow-wayland had to gain
some knowledge about margins:

- xdg_surface_configure() now syncs the shadow after applying the state,
  and gdk_wayland_window_set_shadow_width() possibly reconfigures the
  window in order to preserve window geometry. This is necessary to keep
  shadows in sync with state/geometry changes, as this does not happen
  all at once.
- xdg_popups relative to an xdg_surface are shown relative to buffer
  coordinates, so the left/top margins must be added there.

https://bugzilla.gnome.org/show_bug.cgi?id=736742

gdk/wayland/gdkwindow-wayland.c

index dba476ca42b1a0fa7d7fef8e0745b0c808dc4cdb..4c265467a4844375462590966f34e6b0a36d2fb8 100644 (file)
@@ -683,23 +683,17 @@ static void
 gdk_wayland_window_sync_margin (GdkWindow *window)
 {
   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+  gint x, y, width, height;
 
   if (!impl->xdg_surface)
     return;
 
-  /* XXX: xdg_surface now has xdg_surface_set_window_geometry.
-   *
-   * We need to have a GdkToplevel or some other class in order
-   * to make this work correctly. For now, don't do anything with
-   * the shadow widths.
-   */
-#if 0
-  xdg_surface_set_margin (impl->xdg_surface,
-                          impl->margin_left,
-                          impl->margin_right,
-                          impl->margin_top,
-                          impl->margin_bottom);
-#endif
+  x = impl->margin_left;
+  y = impl->margin_top;
+  width = window->width - (impl->margin_left + impl->margin_right);
+  height = window->height - (impl->margin_top + impl->margin_bottom);
+
+  xdg_surface_set_window_geometry (impl->xdg_surface, x, y, width, height);
 }
 
 static struct wl_region *
@@ -858,8 +852,8 @@ xdg_surface_configure (void               *data,
     {
       gdk_window_constrain_size (&impl->geometry_hints,
                                  impl->geometry_mask,
-                                 width,
-                                 height,
+                                 width + impl->margin_left + impl->margin_right,
+                                 height + impl->margin_top + impl->margin_bottom,
                                  &width,
                                  &height);
 
@@ -889,6 +883,7 @@ xdg_surface_configure (void               *data,
     }
 
   _gdk_set_window_state (window, new_state);
+  gdk_wayland_window_sync_margin (window);
   xdg_surface_ack_configure (xdg_surface, serial);
 }
 
@@ -1025,6 +1020,12 @@ gdk_wayland_window_create_xdg_popup (GdkWindow            *window,
   x = window->x - parent_x;
   y = window->y - parent_y;
 
+  if (parent_impl->xdg_surface)
+    {
+      x -= parent_impl->margin_left;
+      y -= parent_impl->margin_top;
+    }
+
   impl->xdg_popup = xdg_shell_get_xdg_popup (display_wayland->xdg_shell,
                                              impl->surface,
                                              parent_impl->surface,
@@ -2047,10 +2048,22 @@ gdk_wayland_window_set_shadow_width (GdkWindow *window,
                                      int        bottom)
 {
   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+  gint new_width, new_height;
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
+  if (left == impl->margin_left && right == impl->margin_right &&
+      top == impl->margin_top && bottom == impl->margin_bottom)
+    return;
+
+  /* Reconfigure window to keep the same window geometry */
+  new_width = window->width -
+    (impl->margin_left + impl->margin_right) + (left + right);
+  new_height = window->height -
+    (impl->margin_top + impl->margin_bottom) + (top + bottom);
+  gdk_wayland_window_configure (window, new_width, new_height);
+
   impl->margin_left = left;
   impl->margin_right = right;
   impl->margin_top = top;